package com.ojoin.trade.common.web.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ojoin.trade.common.exception.BusinessException;
import com.ojoin.trade.common.utils.CacheUtils;
import com.ojoin.trade.common.utils.CommonUtils;
import com.ojoin.trade.common.utils.IpUtils;
import com.ojoin.trade.common.web.dao.ButtonDao;
import com.ojoin.trade.common.web.dao.SysAreaDao;
import com.ojoin.trade.common.web.dao.DictDao;
import com.ojoin.trade.common.web.dao.MenuDao;
import com.ojoin.trade.common.web.dao.OfficeDao;
import com.ojoin.trade.common.web.dao.RoleDao;
import com.ojoin.trade.common.web.dao.UserDao;
import com.ojoin.trade.common.web.domain.Area;
import com.ojoin.trade.common.web.domain.BaseEntity;
import com.ojoin.trade.common.web.domain.Button;
import com.ojoin.trade.common.web.domain.Dict;
import com.ojoin.trade.common.web.domain.Menu;
import com.ojoin.trade.common.web.domain.Office;
import com.ojoin.trade.common.web.domain.Role;
import com.ojoin.trade.common.web.domain.User;
import com.ojoin.trade.common.web.ldap.LdapSettings;
import com.ojoin.trade.common.web.ldap.support.LdapEntry;
import com.ojoin.trade.common.web.service.DictService;
import com.ojoin.trade.common.web.service.SysManageService;

@Service
public class SysManageServiceImpl implements SysManageService {

	public static final String USER_CACHE = "sys-manageCache";
	public static final String USER_CACHE_ID_ = "id_";
	public static final String USER_CACHE_LOGIN_NAME_ = "ln_";
	public static final String USER_CACHE_LIST_BY_OFFICE_ID_ = "oid_";

	public static final String CACHE_ROLE_LIST = "roleList";
	public static final String CACHE_MENU_LIST = "menuList";
	public static final String CACHE_BUTTON_LIST = "buttonList";
	public static final String CACHE_AREA_LIST = "areaList";
	public static final String CACHE_OFFICE_LIST = "officeList";
	public static final String CACHE_OFFICE_ALL_LIST = "officeAllList";

	
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private RoleDao roleDao;
	
	@Autowired
	private MenuDao menuDao;

	@Autowired
	private ButtonDao buttonDao;
	
	@Autowired 
	private OfficeDao officeDao;
	
	@Autowired 
	private SysAreaDao areaDao;
	
	@Autowired
	private DictService dictService;


	@Autowired
	private org.apache.shiro.cache.CacheManager shiroCacheManager;
	
	/**
	 * 数据范围过滤
	 * 
	 * @param user
	 *            当前用户对象，通过“entity.getCurrentUser()”获取
	 * @param officeAlias
	 *            机构表别名，多个用“,”逗号隔开。
	 * @param userAlias
	 *            用户表别名，多个用“,”逗号隔开，传递空，忽略此参数
	 * @return 标准连接条件对象
	 */
	public String dataScopeFilter(User user, String officeAlias,
			String userAlias) {

		StringBuilder sqlString = new StringBuilder();

		// 进行权限过滤，多个角色权限范围之间为或者关系。
		List<String> dataScope = Lists.newArrayList();

		// 超级管理员，跳过权限过滤
		if (!user.isAdmin()) {
			boolean isDataScopeAll = false;
			for (Role r : user.getRoleList()) {
				for (String oa : StringUtils.split(officeAlias, ",")) {
					if (!dataScope.contains(r.getDataScope())
							&& StringUtils.isNotBlank(oa)) {
						if (Role.DATA_SCOPE_ALL.equals(r.getDataScope())) {
							isDataScopeAll = true;
						} else if (Role.DATA_SCOPE_COMPANY_AND_CHILD.equals(r
								.getDataScope())) {
							sqlString.append(" OR " + oa + ".id = '"
									+ user.getCompany().getId() + "'");
							sqlString.append(" OR " + oa + ".parent_ids LIKE '"
									+ user.getCompany().getParentIds()
									+ user.getCompany().getId() + ",%'");
						} else if (Role.DATA_SCOPE_COMPANY.equals(r
								.getDataScope())) {
							sqlString.append(" OR " + oa + ".id = '"
									+ user.getCompany().getId() + "'");
							// 包括本公司下的部门 （type=1:公司；type=2：部门）
							sqlString.append(" OR (" + oa + ".parent_id = '"
									+ user.getCompany().getId() + "' AND " + oa
									+ ".type = '2')");
						} else if (Role.DATA_SCOPE_OFFICE_AND_CHILD.equals(r
								.getDataScope())) {
							sqlString.append(" OR " + oa + ".id = '"
									+ user.getOffice().getId() + "'");
							sqlString.append(" OR " + oa + ".parent_ids LIKE '"
									+ user.getOffice().getParentIds()
									+ user.getOffice().getId() + ",%'");
						} else if (Role.DATA_SCOPE_OFFICE.equals(r
								.getDataScope())) {
							sqlString.append(" OR " + oa + ".id = '"
									+ user.getOffice().getId() + "'");
						} else if (Role.DATA_SCOPE_CUSTOM.equals(r
								.getDataScope())) {
							// String officeIds =
							// StringUtils.join(r.getOfficeIdList(), "','");
							// if (StringUtils.isNotEmpty(officeIds)){
							// sqlString.append(" OR " + oa + ".id IN ('" +
							// officeIds + "')");
							// }
							sqlString
									.append(" OR EXISTS (SELECT 1 FROM sys_role_office WHERE role_id = '"
											+ r.getId() + "'");
							sqlString.append(" AND office_id = " + oa + ".id)");
						}
						// else if
						// (Role.DATA_SCOPE_SELF.equals(r.getDataScope())){
						dataScope.add(r.getDataScope());
					}
				}
			}
			// 如果没有全部数据权限，并设置了用户别名，则当前权限为本人；如果未设置别名，当前无权限为已植入权限
			if (!isDataScopeAll) {
				if (StringUtils.isNotBlank(userAlias)) {
					for (String ua : StringUtils.split(userAlias, ",")) {
						sqlString.append(" OR " + ua + ".id = '" + user.getId()
								+ "'");
					}
				} else {
					for (String oa : StringUtils.split(officeAlias, ",")) {
						// sqlString.append(" OR " + oa + ".id  = " +
						// user.getOffice().getId());
						sqlString.append(" OR " + oa + ".id IS NULL");
					}
				}
			} else {
				// 如果包含全部权限，则去掉之前添加的所有条件，并跳出循环。
				sqlString = new StringBuilder();
			}
		}
		if (StringUtils.isNotBlank(sqlString.toString())) {
			return " AND (" + sqlString.substring(4) + ")";
		}
		return "";
	}

	/**
	 * 数据范围过滤（符合业务表字段不同的时候使用，采用exists方法）
	 * 
	 * @param entity
	 *            当前过滤的实体类
	 * @param sqlMapKey
	 *            sqlMap的键值，例如设置“dsf”时，调用方法：${sqlMap.sdf}
	 * @param officeWheres
	 *            office表条件，组成：部门表字段=业务表的部门字段
	 * @param userWheres
	 *            user表条件，组成：用户表字段=业务表的用户字段
	 * @example dataScopeFilter(user, "dsf", "id=a.office_id",
	 *          "id=a.create_by"); dataScopeFilter(entity, "dsf", "code=a.jgdm",
	 *          "no=a.cjr"); // 适应于业务表关联不同字段时使用，如果关联的不是机构id是code。
	 */
	public static void dataScopeFilter(BaseEntity<?> entity, String sqlMapKey,
			String officeWheres, String userWheres) {

		User user = entity.getCurrentUser();

		// 如果是超级管理员，则不过滤数据
		if (user.isAdmin()) {
			return;
		}

		// 数据范围（1：所有数据；2：所在公司及以下数据；3：所在公司数据；4：所在部门及以下数据；5：所在部门数据；8：仅本人数据；9：按明细设置）
		StringBuilder sqlString = new StringBuilder();

		// 获取到最大的数据权限范围
		String roleId = "";
		int dataScopeInteger = 8;
		for (Role r : user.getRoleList()) {
			int ds = Integer.valueOf(r.getDataScope());
			if (ds == 9) {
				roleId = String.valueOf(r.getId());
				dataScopeInteger = ds;
				break;
			} else if (ds < dataScopeInteger) {
				roleId = String.valueOf(r.getId());
				dataScopeInteger = ds;
			}
		}
		String dataScopeString = String.valueOf(dataScopeInteger);

		// 生成部门权限SQL语句
		for (String where : StringUtils.split(officeWheres, ",")) {
			if (Role.DATA_SCOPE_COMPANY_AND_CHILD.equals(dataScopeString)) {
				// 包括本公司下的部门 （type=1:公司；type=2：部门）
				sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE");
				sqlString.append(" WHERE type='2'");
				sqlString.append(" AND (id = '" + user.getCompany().getId()
						+ "'");
				sqlString.append(" OR parent_ids LIKE '"
						+ user.getCompany().getParentIds()
						+ user.getCompany().getId() + ",%')");
				sqlString.append(" AND " + where + ")");
			} else if (Role.DATA_SCOPE_COMPANY.equals(dataScopeString)) {
				sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE");
				sqlString.append(" WHERE type='2'");
				sqlString.append(" AND id = '" + user.getCompany().getId()
						+ "'");
				sqlString.append(" AND " + where + ")");
			} else if (Role.DATA_SCOPE_OFFICE_AND_CHILD.equals(dataScopeString)) {
				sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE");
				sqlString.append(" WHERE (id = '" + user.getOffice().getId()
						+ "'");
				sqlString.append(" OR parent_ids LIKE '"
						+ user.getOffice().getParentIds()
						+ user.getOffice().getId() + ",%')");
				sqlString.append(" AND " + where + ")");
			} else if (Role.DATA_SCOPE_OFFICE.equals(dataScopeString)) {
				sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE");
				sqlString.append(" WHERE id = '" + user.getOffice().getId()
						+ "'");
				sqlString.append(" AND " + where + ")");
			} else if (Role.DATA_SCOPE_CUSTOM.equals(dataScopeString)) {
				sqlString
						.append(" AND EXISTS (SELECT 1 FROM sys_role_office ro123456, sys_office o123456");
				sqlString.append(" WHERE ro123456.office_id = o123456.id");
				sqlString.append(" AND ro123456.role_id = '" + roleId + "'");
				sqlString.append(" AND o123456." + where + ")");
			}
		}
		// 生成个人权限SQL语句
		for (String where : StringUtils.split(userWheres, ",")) {
			if (Role.DATA_SCOPE_SELF.equals(dataScopeString)) {
				sqlString.append(" AND EXISTS (SELECT 1 FROM sys_user");
				sqlString.append(" WHERE id='" + user.getId() + "'");
				sqlString.append(" AND " + where + ")");
			}
		}

		// 设置到自定义SQL对象
		entity.getSqlMap().put(sqlMapKey, sqlString.toString());

	}

	/**
	 * 获取当前用户
	 * 
	 * @return 取不到返回 new User()
	 */
	public User getUser() {
		return UserUtils.getUser();
	}
	
	/**
	 * 根据ID获取用户
	 * 
	 * @param id
	 * @return 取不到返回null
	 */
	public User get(Integer id) {
		return UserUtils.get(id);
	}

	public User getFromDB(Integer id){
		return UserUtils.get(id,false);
	}

	/**
	 * 根据登录名获取用户
	 * 
	 * @param loginName
	 * @return 取不到返回null
	 */
	public User getByLoginName(String loginName) {
		User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_
				+ loginName);
		if (user == null) {
			user = userDao.getByLoginName(new User(null, loginName));
			if (user == null) {
				return null;
			}
			user.setRoleList(roleDao.selectList(new Role(user)));
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE,
					USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
		}
		return user;
	}
	
	/**
	 * LDAP sync 2 load
	 */
	public User syncFromLdapEntry(LdapEntry userEntry, LdapSettings ldapSettings, String username){
		User user = getByLoginName(username);

        // create new user object if necessary
        if (user == null) {
            user =new User();
            User cuser=new User(0);
            user.setCreateBy(cuser);
            user.setUpdateBy(cuser);
        }

        // update user attributes from ldap entry
        updateFromLdap(user, userEntry, ldapSettings, username);

        try {
        	saveUser(user);
        } catch (Exception e) {
            return user;
        }

        return user;
    }

    public void updateFromLdap(User user, LdapEntry userEntry, LdapSettings ldapSettings, String username) {
        final String displayNameAttribute = ldapSettings.getDisplayNameAttribute();
        final String fullName =  userEntry.get(displayNameAttribute)!=null?userEntry.get(displayNameAttribute): username;

        user.setName(fullName);
        user.setLoginName(username);
        user.setUserType("0");
        user.setRemarks("External");

        final String email = userEntry.getEmail();
        if (StringUtils.isEmpty(email)) {
            user.setEmail(username + "@localhost");
        } else {
            user.setEmail(email);
        }

        user.setMobile(userEntry.getMobile());
        user.setPassword(userEntry.getPasswd());
        user.setNo("0");
        
        final String company = userEntry.getCompany();
        if (StringUtils.isEmpty(company)) {
        	Office comp=new Office();
            user.setCompany(comp);
        } else {
        	Office compP=new Office();
        	compP.setName(company);
        	user.setCompany(officeDao.findByName(compP));
        }
        
        
        final String office = userEntry.getOffice();
        if (StringUtils.isEmpty(office)) {
        	Office off=new Office();
            user.setOffice(off);
        } else {
        	Office offP=new Office();
        	offP.setName(office);
        	
        	Office compP=new Office();
        	compP.setName(company);
        	
        	offP.setParent(compP);
        	user.setOffice(officeDao.findByName(offP));
        }
        
        // map ldap groups to user roles, if the mapping is present
        final Set<String> translatedRoleIds = Sets.newHashSet(Sets.union(Sets.newHashSet(ldapSettings.getDefaultGroupId()),
                                                                         ldapSettings.getAdditionalDefaultGroupIds()));
        if (!userEntry.getGroups().isEmpty()) {
            // ldap search returned groups, these always override the ones set on the user
                for (String ldapGroupName : userEntry.getGroups()) {
                    final String roleName = ldapSettings.getGroupMapping().get(ldapGroupName);
                    if (roleName == null) {
                        continue;
                    }
                    
                    Role p=new Role();
                    p.setEnname(roleName);
                    
                    final Role role = roleDao.getByEnname(p);
                    if (role != null) {
                        translatedRoleIds.add(String.valueOf(role.getId()));
                    } else {
                    	
                    }
                }
            
        } else if (ldapSettings.getGroupMapping().isEmpty()
                || ldapSettings.getGroupSearchBase().isEmpty()
                || ldapSettings.getGroupSearchPattern().isEmpty()
                || ldapSettings.getGroupIdAttribute().isEmpty()) {
            // no group mapping or configuration set, we'll leave the previously set groups alone on sync
            // when first creating the user these will be empty
            translatedRoleIds.addAll(user.getRoleIdList());
        }
        
        List ids=new ArrayList();
        ids.addAll(translatedRoleIds);
        
        user.setRoleIdList(ids);
    }

	/**
	 * 清除当前用户缓存
	 */
	public  void clearCache(){
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_MENU_LIST);
		removeCache(CACHE_AREA_LIST);
		removeCache(CACHE_OFFICE_LIST);
		removeCache(CACHE_OFFICE_ALL_LIST);
		clearCache(getUser());
	}
	/**
	 * 清除指定用户缓存
	 * 
	 * @param user
	 */
	public  void clearCache(User user) {
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(USER_CACHE,
				USER_CACHE_LOGIN_NAME_ + user.getLoginName());
		CacheUtils.remove(USER_CACHE,
				USER_CACHE_LOGIN_NAME_ + user.getOldLoginName());

		 //rm authCache
		com.ojoin.trade.common.web.shiro.cache.JedisCacheManager.JedisCache<Object, Object> cache = (com.ojoin.trade.common.web.shiro.cache.JedisCacheManager.JedisCache) shiroCacheManager.getCache("com.ojoin.trade.common_core.web.shiro.SystemAuthorizingRealm.authorizationCache");
		if(null!=cache){
			cache.remove(user.getLoginName());
		}


		if (user.getOffice() != null && user.getOffice().getId() != null) {
			CacheUtils.remove(USER_CACHE, USER_CACHE_LIST_BY_OFFICE_ID_
					+ user.getOffice().getId());
		}
	}

	/**
	 * 无分页查询人员列表
	 * 
	 * @param user
	 * @return
	 */
	public List<User> findUser(User user) {
		// 生成数据权限过滤条件（dsf为dataScopeFilter的简写，在xml中使用 ${sqlMap.dsf}调用权限SQL）
		user.getSqlMap().put("dsf",
				dataScopeFilter(user.getCurrentUser(), "o", "a"));
		List<User> list = userDao.selectList(user);
		return list;
	}

	public List<User> findUser(User user,Pageable page){
			user.getSqlMap().put("dsf", dataScopeFilter(user.getCurrentUser(), "o", "a"));
			return userDao.selectList(user, page);
	}
	
	/**
	 * 通过部门ID获取用户列表，仅返回用户id和name（树查询用户时用）
	 * 
	 * @param officeId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<User> findUserByOfficeId(Integer officeId) {
		List<User> list = (List<User>) CacheUtils.get(USER_CACHE,
				USER_CACHE_LIST_BY_OFFICE_ID_ + officeId);
		if (list == null) {
			User user = new User();
			user.setOffice(new Office(officeId));
			list = userDao.findUserByOfficeId(user);
			CacheUtils.put(USER_CACHE,
					USER_CACHE_LIST_BY_OFFICE_ID_ + officeId, list);
		}
		return list;
	}

	public void saveUser(User user) {
		if (null == user.getId()) {
			user.preInsert();
			userDao.insert(user);
		} else {
			// 清除原用户机构用户缓存
			User oldUser = userDao.selectById(user.getId());
			if (oldUser.getOffice() != null
					&& oldUser.getOffice().getId() != null) {
				CacheUtils.remove(USER_CACHE, USER_CACHE_LIST_BY_OFFICE_ID_
						+ oldUser.getOffice().getId());
			}
			// 更新用户数据
			user.preUpdate();
			userDao.updateById(user);
		}
		if (null != user.getId()) {
			// 更新用户与角色关联
			userDao.deleteUserRole(user);
			if (user.getRoleList() != null && user.getRoleList().size() > 0) {
				userDao.insertUserRole(user);
			} else {
				throw new BusinessException(user.getLoginName() + "没有设置角色！");
			}
			// 清除用户缓存
			clearCache(user);
			getUser();
		}
	}

	public void updateUserInfo(User user) {
		user.preUpdate();
		userDao.updateUserInfo(user);
		// 清除用户缓存
		clearCache(user);
		getUser();
	}

	public void deleteUser(User user) {
		userDao.delete(user);
		// 清除用户缓存
		clearCache(user);
		getUser();
	}

	public void updatePasswordById(Integer id, String loginName,
			String newPassword) {
		User user = new User(id);
		user.setPassword(UserUtils.entryptPassword(newPassword));
		userDao.updatePasswordById(user);
		// 清除用户缓存
		user.setLoginName(loginName);
		clearCache(user);
		getUser();
	}

	public void updateUserLoginInfo(User user) {
		// 保存上次登录信息
		user.setOldLoginIp(user.getLoginIp());
		user.setOldLoginDate(user.getLoginDate());
		// 更新本次登录信息
		String ip = IpUtils.getIpAddr(CommonUtils.getRequest());
		user.setLoginIp(ip);
		user.setLoginDate(new Date());
		userDao.updateLoginInfo(user);
	}

	/**
	 * 获取当前用户角色列表
	 * 
	 * @return
	 */
	public List<Role> getRoleList() {
		List<Role> roleList = (List<Role>) getCache(CACHE_ROLE_LIST);
		if (roleList == null) {
			User user = getUser();
			if (user.isAdmin()) {
				roleList = roleDao.selectAll();
			} else {
				Role role = new Role();
				role.getSqlMap().put("dsf",
						dataScopeFilter(user.getCurrentUser(), "o", "u"));
				roleList = roleDao.selectList(role);
			}
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}
	
	
	public List<Role> getRoleListByUserId(Integer userid) {
		List<Role> roleList = (List<Role>) getCache(CACHE_ROLE_LIST);
		if (roleList == null) {
				User user = userDao.selectById(userid);
				Role role = new Role();
				role.getSqlMap().put("dsf",
						dataScopeFilter(user.getCurrentUser(), "o", "u"));
				roleList = roleDao.selectList(role);
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}
	
	/**
	 * 获取当前用户授权菜单
	 * 
	 * @return
	 */
	public List<Menu> getMenuList() {
		List<Menu> menuList = (List<Menu>) getCache(CACHE_MENU_LIST);
		if (menuList == null) {
			User user = getUser();
			if (user.isAdmin()) {
				menuList = menuDao.selectAll();
			} else {
				Menu m = new Menu();
				m.setUserId(user.getId());
				menuList = menuDao.findByUserId(m);
			}
			putCache(CACHE_MENU_LIST, menuList);
		}
		return menuList;
	}

	/**
	 * 获取当前用户授权按钮
	 * 
	 * @return
	 */
	public List<Button> getButtonList() {
		List<Button> buttonList = (List<Button>) getCache(CACHE_BUTTON_LIST);
		if (buttonList == null) {
			User user = getUser();
			if (user.isAdmin()) {
				buttonList = buttonDao.selectAll();
			} else {
				Button m = new Button();
				m.setUserId(user.getId());
				buttonList = buttonDao.findByUserId(m);
			}
			putCache(CACHE_BUTTON_LIST, buttonList);
		}
		return buttonList;
	}
	
	/**
	 * 获取当前用户授权的区域
	 * @return
	 */
	public  List<Area> getAreaList(){
		List<Area> areaList = (List<Area>)getCache(CACHE_AREA_LIST);
		if (areaList == null){
			areaList = areaDao.selectAll();
			putCache(CACHE_AREA_LIST, areaList);
		}
		return areaList;
	}
	
	/**
	 * 获取当前用户有权限访问的部门
	 * @return
	 */
	public  List<Office> getOfficeList(){
		List<Office> officeList = (List<Office>)getCache(CACHE_OFFICE_LIST);
		if (officeList == null){
			User user = getUser();
			if (user.isAdmin()){
				officeList = officeDao.selectAll();
			}else{
				Office office = new Office();
				office.getSqlMap().put("dsf", dataScopeFilter(user, "a", ""));
				officeList = officeDao.selectList(office);
			}
			putCache(CACHE_OFFICE_LIST, officeList);
		}
		return officeList;
	}

	/**
	 * 获取当前用户有权限访问的部门
	 * @return
	 */
	public  List<Office> getOfficeAllList(){
		List<Office> officeList = (List<Office>)getCache(CACHE_OFFICE_ALL_LIST);
		if (officeList == null){
			officeList = officeDao.selectAll();
		}
		return officeList;
	}
	
	public Menu getMenu(Integer id) {
		return menuDao.selectById(id);
	}

	public Button getButton(Integer id) {
		return buttonDao.selectById(id);
	}
	
	public List<Menu> findAllMenu() {
		return getMenuList();
	}

	public List<Object> findAllMenuAndButton() {
		List<Object> list = new ArrayList<Object>();
		List<Menu> menuList = getMenuList();
		List<Button> buttonList = getButtonList();
		list.addAll(menuList);
		list.addAll(buttonList);
		
		return list;
	}
	
	public List<Button> findAllButton() {
		return getButtonList();
	}
	
	public void saveMenu(Menu menu) {

		// 获取父节点实体
		menu.setParent(this.getMenu(menu.getParent().getId()));

		// 获取修改前的parentIds，用于更新子节点的parentIds
		String oldParentIds = menu.getParentIds();

		// 设置新的父节点串
		menu.setParentIds(menu.getParent().getParentIds()
				+ menu.getParent().getId() + ",");

		// 保存或更新实体
		if (null == menu.getId()) {
			menu.preInsert();
			menuDao.insert(menu);
		} else {
			menu.preUpdate();
			menuDao.updateById(menu);
		}

		// 更新子节点 parentIds
		Menu m = new Menu();
		m.setParentIds("%," + menu.getId() + ",%");
		List<Menu> list = menuDao.findByParentIdsLike(m);
		for (Menu e : list) {
			e.setParentIds(e.getParentIds().replace(oldParentIds,
					menu.getParentIds()));
			menuDao.updateParentIds(e);
		}
		// 清除用户菜单缓存
		removeCache(CACHE_MENU_LIST);

	}

	public void saveButton(Button button) {
		// 保存或更新实体
		if (null == button.getId()) {
			button.preInsert();
			buttonDao.insert(button);
		} else {
			button.preUpdate();
			buttonDao.updateById(button);
		}

		// 清除用户按钮缓存
		removeCache(CACHE_BUTTON_LIST);

	}
	
	public void updateMenuSort(Menu menu) {
		menuDao.updateSort(menu);
		// 清除用户菜单缓存
		removeCache(CACHE_MENU_LIST);
	}

	public void deleteMenu(Menu menu) {
		menuDao.delete(menu);
		// 清除用户菜单缓存
		removeCache(CACHE_MENU_LIST);
	}

	public void deleteButton(Button button) {
		buttonDao.delete(button);
		// 清除用户按钮缓存
		removeCache(CACHE_BUTTON_LIST);
	}
	
	public Role getRole(Integer id) {
		return roleDao.selectById(id);
	}

	public Role getRoleByName(String name) {
		Role r = new Role();
		r.setName(name);
		return roleDao.getByName(r);
	}

	public Role getRoleByEnname(String enname) {
		Role r = new Role();
		r.setEnname(enname);
		return roleDao.getByEnname(r);
	}

	public List<Role> findRole(Role role) {
		return roleDao.selectList(role);
	}

	public List<Role> findAllRole() {
		return getRoleList();
	}

	public void saveRole(Role role) {
		if (null == role.getId()) {
			role.preInsert();
			roleDao.insert(role);

		} else {
			role.preUpdate();
			roleDao.updateById(role);
		}
		// 更新角色与菜单关联
		roleDao.deleteRoleMenu(role);
		if (role.getMenuList().size() > 0) {
			roleDao.insertRoleMenu(role);
		}
		// 更新角色与部门关联
		roleDao.deleteRoleOffice(role);
		if (role.getOfficeList().size() > 0) {
			roleDao.insertRoleOffice(role);
		}
		// 更新角色与菜单按钮关联
		roleDao.deleteRoleButton(role);
		if (role.getButtonList().size() > 0) {
			roleDao.insertRoleButton(role);
		}
		
		// 清除用户角色缓存
		removeCache(CACHE_ROLE_LIST);
	}

	public void deleteRole(Role role) {
		roleDao.delete(role);
		removeCache(CACHE_ROLE_LIST);
	}

	public Boolean outUserInRole(Role role, User user) {
		List<Role> roles = user.getRoleList();
		for (Role e : roles) {
			if (e.getId().equals(role.getId())) {
				roles.remove(e);
				saveUser(user);
				return true;
			}
		}
		return false;
	}

	public User assignUserToRole(Role role, User user) {
		if (user == null) {
			return null;
		}
		List<String> roleIds = user.getRoleIdList();
		if (roleIds.contains(String.valueOf(role.getId()))) {
			return null;
		}
		user.getRoleList().add(role);
		saveUser(user);
		return user;
	}

	public   String getDictLabel(String value, String type, String defaultValue){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(value)){
			for (Dict dict : getDictList(type)){
				if (type.equals(dict.getType()) && value.equals(dict.getValue())){
					return dict.getLabel();
				}
			}
		}
		return defaultValue;
	}
	
	public   String getDictLabels(String values, String type, String defaultValue){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(values)){
			List<String> valueList = Lists.newArrayList();
			for (String value : StringUtils.split(values, ",")){
				valueList.add(getDictLabel(value, type, defaultValue));
			}
			return StringUtils.join(valueList, ",");
		}
		return defaultValue;
	}

	public   String getDictValue(String label, String type, String defaultLabel){
		if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){
			for (Dict dict : getDictList(type)){
				if (type.equals(dict.getType()) && label.equals(dict.getLabel())){
					return dict.getValue();
				}
			}
		}
		return defaultLabel;
	}
	
	public   List<Dict> getDictList(String type){
		Map<String, List<Dict>> dictMap = Maps.newHashMap();
		for (Dict dict : dictService.queryAll()){
			List<Dict> dictList = dictMap.get(dict.getType());
			if (dictList != null){
				dictList.add(dict);
			}else{
				dictMap.put(dict.getType(), Lists.newArrayList(dict));
			}
		}
		List<Dict> dictList = dictMap.get(type);
		if (dictList == null){
			dictList = Lists.newArrayList();
		}
		return dictList;
	}
	// ============== User Cache ==============

	public static Object getCache(String key) {
		return getCache(key, null);
	}

	public static Object getCache(String key, Object defaultValue) {
		Object obj = CommonUtils.getShiroSession().getAttribute(key);
		return obj == null ? defaultValue : obj;
	}

	public static void putCache(String key, Object value) {
		CommonUtils.getShiroSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
		CommonUtils.getShiroSession().removeAttribute(key);
	}

}
